package com.icare.common.service.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

/**
 * 比较对象差异工具类
 *
 * @author TianHaibo
 * @create 2018-01-05 17:00
 **/
public class CompareDifferUtil {

    /**
     *
     * @param oldObj    旧对象
     * @param newObj    新对象
     * @param <T>       入参类型
     * @return  差异属性的josn字符串
     * @throws Exception
     */
        private static <T> String  compare(T oldObj,T newObj) throws Exception{
            if(oldObj == null && newObj == null){
                return null;
            }
            if(oldObj == null){
                throw new RuntimeException("旧对象不能为空....");
            }
            Method[] methods = oldObj.getClass().getMethods();
            List<Object> result = new LinkedList<>();
            for (Method m:methods) {
                if(m.getName().startsWith("get")
                        ||m.getName().startsWith("is")){
                    String fieldName = m.getName();
                    if(fieldName.startsWith("get"))
                        fieldName = fieldName.substring(3,4).toLowerCase().concat(fieldName.substring(4));
                    else
                        fieldName = fieldName.substring(2,3).toLowerCase().concat(fieldName.substring(3));
                    Object invokeNewResult = m.invoke(newObj);
                    if(invokeNewResult == null)
                        continue;
                    Object invokeOldResult = m.invoke(oldObj);
                    //如果属性类型为集合
                    if(invokeNewResult instanceof Collection){
                        DifferCollectionDto collectionDto = compareCollection(fieldName,(Collection)invokeOldResult,(Collection)invokeNewResult);
                        if(collectionDto!=null)
                            result.add(collectionDto);
                        continue;
                    }
                    //如果属性类型不是集合
                    if(!invokeNewResult.equals(invokeOldResult))
                        result.add(new DifferDto(fieldName,invokeOldResult,invokeNewResult));
                }
            }
            return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue);
        }

    /**
     * 比较两个集合类型的属性
     * @param invokeOldResult
     * @param invokeNewResult
     * @return
     */
    private static DifferCollectionDto compareCollection(String fieldName,Collection invokeOldResult, Collection invokeNewResult) {
        if(invokeNewResult == null || invokeNewResult.size() == 0){
            return null;
        }
        if(invokeOldResult == null || invokeOldResult.size() == 0){
            return new DifferCollectionDto(fieldName,invokeNewResult,null);
        }
        HashSet<Object> intersection = new HashSet<>(invokeNewResult);//交集元素存放(未变更元素)
        HashSet<Object> newResult = new HashSet<>(invokeNewResult);//新增元素存放
        HashSet<Object> oldResult = new HashSet<>(invokeOldResult);//删除元素存放
        intersection.retainAll(oldResult);
        oldResult.removeAll(intersection);
        newResult.removeAll(intersection);
        if((oldResult == null || oldResult.size() == 0)){
            oldResult = null;
        }
        if((newResult == null || newResult.size() == 0)){
            newResult = null;
        }
        if(oldResult == null && newResult == null){
            return null;
        }else{
            return new DifferCollectionDto(fieldName,newResult,oldResult);
        }
    }

    @Data
    @AllArgsConstructor
    private static class DifferDto{

        private String fieldName;//字段名称
        private Object oldV;//老的值
        private Object newV;//新的值

    }

    @Data
    @AllArgsConstructor
    private static class DifferCollectionDto{

        private String fieldName;//字段名称
        private Collection addColl;//新增的值
        private Collection deleteColl;//删除的值

    }
/*
    public static void main(String[] args) throws Exception {
        ArrayList<BigDecimal> bigDecimals1 = new ArrayList<>();
        bigDecimals1.add(new BigDecimal("100"));
        bigDecimals1.add(new BigDecimal("101"));
        bigDecimals1.add(new BigDecimal("99"));
        bigDecimals1.add(new BigDecimal("98"));
        bigDecimals1.add(new BigDecimal("97"));

        ArrayList<BigDecimal> bigDecimals2 = new ArrayList<>();
        bigDecimals2.add(new BigDecimal("99"));
        bigDecimals2.add(new BigDecimal("98"));
        bigDecimals2.add(new BigDecimal("97"));
//        bigDecimals2.add(new BigDecimal("96"));
//        bigDecimals2.add(new BigDecimal("95"));
        Student student1 = new Student(1L, "田AA", null,new BigDecimal("2000"),bigDecimals1);
        Student student2 = new Student(2L,"田BB",22,new BigDecimal("3000"),bigDecimals2);
        Student student3 = new Student(3L,"田CC",24,new BigDecimal("4000"),null);
        String compare = compare(student1, student2);
        System.out.println(compare);
    }

    @Data
    @AllArgsConstructor
    private static class Student{
        private Long id;
        private String name;
        private Integer age;
        private BigDecimal salary;
        private List<BigDecimal> scores;
    }*/
}
